/*
 * @Description: 评论面板
 * @version: 1.0.0
 * @Author: YinJianFeng
 * @Date: 2024-08-31 17:06:27
 */

import {
  cadAppLog,
  CMEVENTS,
  pickedFaceData,
  pickedLineData,
  pickedVertexData,
  PickType,
  Types,
} from '@amcax/base';
import { ctx2, docMgr, userEvents, widgetManager } from '@app-cad/module';
import React, { useEffect, useState } from 'react';
import MarksItem from './MarksItem';
import './style.scss';
import { markManager } from '@app-cad/common/managers/MarkManager';
import { Mark } from '@app-cad/types';
import MarkInput from './MarkInput';
import { MARK_EVENT } from '@app-cad/common/Constants';
import { Empty } from 'antd';
import { useMemoizedFn } from 'ahooks';
import { Vector3 } from 'three-legacy';
import { eventCenterManager } from '@app-cad/common/events/EventCenterManager';

export interface IMarksItem {
  dxid: string;
}

export enum MarkComponentOrigin {
  // 右侧侧边栏显示
  Panel = 'Panel',
  // 元素上连线延伸出来，悬浮显示
  Float = 'Float',
}

export default function MarksPanel() {
  const [marks, setMarks] = useState<Mark[]>([]);
  const [pickedObject, setPickedObject] = useState<
    pickedVertexData | pickedLineData | pickedFaceData
  >();

  const [position, setPosition] = useState<Vector3>();

  const width = 300;

  useEffect(() => {
    onOpen();
    registerEvents();

    return () => {
      onClose();
      unregisterEvents();
    };
  }, []);

  useEffect(() => {
    if (
      pickedObject != null &&
      marks.every((mark) => mark.dxid !== pickedObject.idInfo.o)
    ) {
      setPickedObject(null);
    }
  }, [marks]);

  const onMarkPickedObject = useMemoizedFn((pickedObject) => {
    setPickedObject(pickedObject);
  });

  const onModelSelected = useMemoizedFn(
    (selectedTarget: pickedFaceData | pickedLineData | pickedVertexData) => {
      if (selectedTarget?.assisObj != null) {
        const documentObject = docMgr.getDocumentObjectById(
          selectedTarget.idInfo.o,
        );

        if (
          [Types.BASIC_PLANE, Types.ORIGIN, Types.Sketcher].includes(
            documentObject?.type,
          )
        ) {
          setPickedObject(null);
          return;
        }
        setPickedObject(selectedTarget);

        if (eventCenterManager.activeEventCenter.mouse != null) {
          const rayCaster = ctx2.viewer.sceneSetup.createRaycaster(
            eventCenterManager.activeEventCenter.mouse.x,
            eventCenterManager.activeEventCenter.mouse.y,
            null,
            10,
          );

          const res = rayCaster.intersectObjects(
            [selectedTarget.assisObj],
            true,
          );
          const point =
            selectedTarget.idInfo.t === PickType.LINE
              ? ((res[0] as any)?.pointOnLine ?? res[0]?.point)
              : res[0]?.point;

          setPosition(point && new Vector3(point.x, point.y, point.z));
        }
      }
    },
  );

  const onRightNavChange = useMemoizedFn(({ id, component }) => {
    if (id !== 'mark') {
      return;
    }

    if (component != null) {
      onOpen();
    } else {
      onClose();
    }
  });

  const registerEvents = () => {
    userEvents.on(CMEVENTS.MESH_SELECTED, onModelSelected);
    userEvents.on(CMEVENTS.EDGE_SELECTED, onModelSelected);
    userEvents.on(CMEVENTS.POINT_SELECTED, onModelSelected);
    userEvents.on(CMEVENTS.ENV_CHANGED, onClose);
    userEvents.on(CMEVENTS.RIGHT_NAV_ITEM_CLICK, onRightNavChange);

    userEvents.on(MARK_EVENT.MARK_PICKED_OBJECT, onMarkPickedObject);
    userEvents.on(MARK_EVENT.MARK_UPDATED, onMarkUpdated);
  };
  const unregisterEvents = () => {
    userEvents.off(CMEVENTS.MESH_SELECTED, onModelSelected);
    userEvents.off(CMEVENTS.EDGE_SELECTED, onModelSelected);
    userEvents.off(CMEVENTS.POINT_SELECTED, onModelSelected);
    userEvents.off(CMEVENTS.ENV_CHANGED, onClose);
    userEvents.off(CMEVENTS.RIGHT_NAV_ITEM_CLICK, onRightNavChange);

    userEvents.off(MARK_EVENT.MARK_PICKED_OBJECT, onMarkPickedObject);
    userEvents.off(MARK_EVENT.MARK_UPDATED, onMarkUpdated);
  };

  const onMarkUpdated = useMemoizedFn(() => {
    cadAppLog('[debug]MARK_UPDATED', markManager.marks);
    setMarks(markManager.marks);
  });

  const onOpen = useMemoizedFn(async () => {
    userEvents.emit(CMEVENTS.RIGHT_PANEL_TOGGLE, { open: true, width });

    cadAppLog('[debug]打开评论面板');
    await markManager.showAllMarks();
    setMarks(markManager.marks);

    const pickedObject = widgetManager.rightNavigation.getParams('mark');
    setPickedObject(pickedObject);
    cadAppLog('[debug]pickedObject', pickedObject);
  });
  const onClose = useMemoizedFn(() => {
    userEvents.emit(CMEVENTS.RIGHT_PANEL_TOGGLE, { open: false, width });
    cadAppLog('[debug]关闭评论面板');
    markManager.hideAllMarks();
  });

  return (
    <>
      <div
        className='comment-panel'
        style={{ width: width + 'px', height: '100%' }}
      >
        <div className='body'>
          {marks.length === 0 && (
            <div
              className='absolute top-1/2 left-1/2'
              style={{ transform: 'translate(-50%,-50%)' }}
            >
              <Empty description='暂无标签内容' />
            </div>
          )}
          {marks.length > 0 &&
            marks.map((mark) => {
              return <MarksItem mark={mark} />;
            })}
        </div>
        <div className='footer'>
          <MarkInput
            pickedObject={pickedObject}
            position={position}
            afterSubmit={() => {
              setPickedObject(null);
            }}
          />
        </div>
      </div>
    </>
  );
}
